home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Testing & Debugging / Virtual User tools / VU Assist Modules for MacApp / Assist Module MA 2.0.1 / VUAssist Source Code / UVUAssist.inc2.p < prev    next >
Encoding:
Text File  |  1993-09-17  |  42.7 KB  |  1,482 lines  |  [TEXT/MPS ]

  1. (*+
  2.  *    File:        UVUAssist.inc2.p
  3.  *
  4.  *    Contains:    VU assistance methods
  5.  *
  6.  *    Written by:    David Shayer
  7.  *
  8.  *    Copyright:    © 1991 by Apple Computer, Inc., all rights reserved.
  9.  *
  10.  *  Version: 1.0d10
  11.  *
  12.  *    Change History (most recent first):
  13.  
  14.          9/3/91        JAS        Change references to 'mole' in debug strings to 'Agent VU'
  15.          8/29/91    JAS     implement MyWMgrToWindow method, bump version to 1.0d10
  16.          8/21/91    JAS        adjust comments, change version
  17.          8/19/91    JAS        change case of of GridItemSupport to gridItemSupport
  18.          8/15/91    JAS        Add GridItemSupport argument to IVUAssist
  19.          8/13/91    JAS        Revise comments
  20.          8/13/91    JAS        Change made in GetItemType so that kIncludeGridItems 
  21.                              will determine whether TGridItems are ever identified for use 
  22.          8/13/91    JAS        Make changes in IVUAssist since VUAssist is now a descendant
  23.                              of TEvtHandler (sets idle frequency and installs cohandler).
  24.          8/13/91    JAS        Changes in TGridItem implementation
  25.          8/13/91    JAS        Use FirstSubViewThat in place of EachSubView wherever applicable
  26.          8/6/91        JAS        Clean up change history
  27.          8/6/91        JAS        Check for GridViewItems in GetItemType only if DlogViewItems is
  28.                             true, remove TVUAssist.DoFindWindowInfo (not needed)
  29. -*)
  30.  
  31. {Historical Note:  References to the "Mole" are equivalent to references to "Agent VU".
  32. "Agent VU" was previously called the "Mole".}
  33.  
  34.  
  35. { The mole sees MacApp windows as plain windows that are empty.  MacApp
  36. doesn't put its controls in the control list, so V.U. won't even see standard
  37. Control Manager controls.  The assistance proc updates the mole buffer before
  38. it is sent back to the V.U. host, telling it that there are items in the windows, 
  39. and telling it about each item.  We tell it that the windows are dialogs, 
  40. because V.U. looks for a wider range of user interface items in dialogs.
  41.  
  42. V.U. has its own hierarchy of user interface items, based largely on the types of 
  43. interface items defined in Inside Mac which V.U. can obtain information about
  44. in non-MacApp applications.  MacApp's user interface element hierarchy is the View hierarchy.  
  45. Since the two hierarchies are not the same, VUAssist must perform a mapping between the
  46. two hierarchies.  Many of these mappings are straight-forward, but a few require some
  47. explanation.  The V.U. interface item hierarchy is as follows.  
  48.  
  49.                 |___ staticText
  50.                 |                       
  51.                 |___ editText                       
  52.                 |                                          
  53.                 |___ picture
  54. contentItem-----|
  55.                 |___ icon                       
  56.                 |                                          
  57.                 |___ userItem
  58.                 |
  59.                 |___ control-----|___ button
  60.                                   |                       
  61.                                   |___ checkBox    
  62.                                  |
  63.                                  |___ radioButton
  64.                                   |                       
  65.                                   |___ scrollBar
  66.                                  |                       
  67.                                   |___ popup
  68.                                  
  69. All V.U. interface items are considered contentItems.  Some of these contentItems are 
  70. typically found only in Dialog Manager dialogs in non-MacApp applications.  These would 
  71. be staticText, editText, picture, icon, and userItem.  Controls are Control Manager controls
  72. which may appear in any window.
  73.  
  74. The list of TView descendants which are mapped to V.U. interface items and the V.U. item
  75. to which they are mapped by V.U. by way of VUAssist is shown below.
  76.  
  77. TStaticText ---------> staticText
  78. TEditText     ---------> editText
  79. TPicture     ---------> picture
  80. TIcon         ---------> icon
  81. TButton     ---------> button
  82. TCheckbox     ---------> checkBox
  83. TRadio         ---------> radioButton
  84. TScrollBar     ---------> scrollBar
  85. TPopup         ---------> popup
  86. TTextEdit     ---------> editText
  87. (cells of TGridView -> contentItem)  - an optional feature
  88.  
  89. The last item, "cells of TGridView", deserves some explanation. TGridViews are a 
  90. problem because unlike all the other items mentioned above, where there is exactly one 
  91. MacApp object for each user interface item, there are many user interface items for a 
  92. single TGridView object.  V.U. does not yet directly support gridView types of objects.  
  93. So there is special case code for TGridViews.  Each cell in a grid is passed back as a 
  94. "CUSTOM_ITEM".  To V.U., a CUSTOM_ITEM is a user interface item which does not fall into
  95. any category more specific than contentItem.  So from a V.U. script writer's perspective,
  96. cells in TGridView objects are V.U. contentItems.
  97.  
  98. Note that the mapping of TGridView cells to contentItems is a feature which can be disabled.
  99. TVUAssist's IVUAssist method takes a boolean argument gridItemSupport.  By passing 'false'
  100. to this method, the cells of TGridViews are invisible to V.U..  You may want to do this if 
  101. your application has large gridviews or many gridviews.  In this case treating each cell as
  102. an interface item may bog down V.U. in such a way that performance is not acceptable. 
  103.  
  104. You'll also note in the code that we include TPopup descriptions in response to V.U.'s requests 
  105. for information about controls.  This is because V.U. can normally only support popups which 
  106. are implemented through the use of the popup CDEF found in System 7.0 or in the Mac Communications 
  107. Toolbox.  So V.U. expects them to be controls.}
  108.  
  109.  
  110. {========================================== TVUAssist ================================}
  111.  
  112. {$S VUAssistSeg}
  113.  
  114. {The MoleHook is declared as type C, which means it must be an external function.
  115. The actual code for MoleHook is in assembly.  All it does is accept the call from the mole
  116. with a C interface, and then call TVUAssist.MoleAssist with a Pascal interface.}
  117. FUNCTION MoleHook (Select :integer; Input :Ptr; VAR OutputSize :integer;
  118.     Result :integer) :OSErr; C; EXTERNAL;
  119.  
  120.  
  121. { IVUAssist initializes fMoleRefNum.  fMoleRefNum contains the reference number of the 
  122. mole driver, or 0 if no mole driver has been found yet. Also initializes VUAssist as an EvtHandler, 
  123. sets idle frequency to kVUAssistIdleFreq, and installs cohandler.  Also initializes fGridItemSupport
  124. according to input argument gridItemSupport.}
  125. PROCEDURE TVUAssist.IVUAssist(gridItemSupport: boolean);
  126. BEGIN
  127.     {$IFC qDebug}
  128.         gVUDebug:=false;
  129.         DebugFlag(@gVUDebug,'9', NIL, AtStr('VU Assist'));
  130.     {$ENDC}
  131.     INHERITED IEvtHandler(NIL);
  132.     fGridItemSupport:=gridItemSupport;
  133.     fMoleRefNum:=0;
  134.     SELF.OpenMoleDriver;
  135.     SELF.SetIdleFreq(kVUAssistIdleFreq);
  136.     gApplication.InstallCohandler(SELF, true);
  137. END;
  138.  
  139.  
  140. { Try to open the mole driver if there is one. }
  141. PROCEDURE TVUAssist.OpenMoleDriver;
  142. VAR
  143.     PBRec :ParamBlockRec;
  144.     Err :integer;
  145.     MoleName :Str15;
  146. BEGIN
  147.     MoleName:='.Mole';
  148.     PBRec.ioCompletion:=NIL;
  149.     PBRec.ioNamePtr:=@MoleName;
  150.     PBRec.ioPermssn:=fsCurPerm;
  151.     Err:=PBOpen (@PBRec, false);
  152.     IF (PBRec.ioResult=noErr) THEN
  153.     BEGIN
  154.         {$IFC qDebug}
  155.             WriteLn ('Agent VU Contacted');
  156.         {$ENDC}
  157.         fMoleRefNum:=PBRec.ioRefNum;
  158.         SELF.ResumeMole;
  159.     END;
  160. END;
  161.  
  162.  
  163. { Call this routine when the application is suspended by Multifinder, to let
  164. the mole know we are no longer the frontmost app. }
  165. PROCEDURE TVUAssist.SuspendMole;
  166. BEGIN
  167.     SELF.SetDebuggerHook(NIL);
  168. END;
  169.  
  170.  
  171. { Call this routine when MultiFinder puts us back into the foreground. }
  172. PROCEDURE TVUAssist.ResumeMole; 
  173. BEGIN
  174.     SELF.SetDebuggerHook(@MoleHook);
  175. END;
  176.  
  177.  
  178.  
  179. { Tell the mole the address of our assistance procedure.}
  180. PROCEDURE TVUAssist.SetDebuggerHook (NewHook :ProcPtr); 
  181. CONST
  182.     SET_ASSIST = 100;
  183. VAR
  184.     PBRec :ParamBlockRec;
  185.     Err :integer;
  186.     LongPtr :^Longint;
  187. BEGIN
  188.     IF (fMoleRefNum<>0) THEN
  189.     BEGIN
  190.         PBRec.ioCompletion:=NIL;
  191.         PBRec.ioVRefNum:=0;
  192.         PBRec.ioRefNum:=fMoleRefNum;
  193.         PBRec.csCode:=SET_ASSIST;
  194.         LongPtr:=@PBRec.csParam[0];
  195.         LongPtr^:=LongInt(NewHook);
  196.         Err:=PBControl (@PBRec, false);
  197.         IF (PBRec.ioResult<>noErr) THEN
  198.             WriteLn ('Error sending Agent VU control call');
  199.     END;
  200. END;
  201.  
  202.  
  203.  
  204. { This is the routine called by MoleHook.  It dispatches out to the routines
  205. which actually assist the mole. }
  206. FUNCTION TVUAssist.MoleAssist (Select :integer; Input :Ptr; Output :Ptr; 
  207.     VAR OutputSize :integer; IntResult :integer) :integer;
  208. VAR
  209.     Result        :MoleError;
  210.     ReturnValue    :MoleError;
  211. BEGIN
  212.     Result:=MoleError(IntResult);
  213.     ReturnValue:=Result;
  214.     CASE MoleSelectors(Select) OF
  215.         SMenuInfo:
  216.             BEGIN
  217.                 ReturnValue:=SELF.DoMenuInfo (Input, Output, OutputSize, Result);
  218.             END;
  219.         SMenuItems:
  220.             BEGIN
  221.                 ReturnValue:=SELF.DoMenuItems (Input, Output, OutputSize, Result);
  222.             END;
  223.         SetMItemKey:
  224.             BEGIN
  225.                 {$IFC qDebug}
  226.                     IF gVUDebug THEN
  227.                         WriteLn ('* SetMItemKey');
  228.                 {$ENDC}
  229.             END;
  230.         SFrontWind:
  231.             BEGIN
  232.                 {$IFC qDebug}
  233.                     IF gVUDebug THEN
  234.                         WriteLn ('* SFrontWind');
  235.                 {$ENDC}
  236.             END;
  237.         SFindWind:
  238.             BEGIN
  239.                 {$IFC qDebug}
  240.                     IF gVUDebug THEN
  241.                         WriteLn ('* SFindWind');
  242.                 {$ENDC}
  243.             END;
  244.         SWindInfo:
  245.             BEGIN
  246.                 ReturnValue:=SELF.DoSendWindowInfo (Input, Output, OutputSize, Result);
  247.             END;
  248.         SFindCtl:
  249.             BEGIN
  250.                 ReturnValue:=SELF.DoFindControl (Input, Output, OutputSize, Result);
  251.             END;
  252.         SCtlInfo:
  253.             BEGIN
  254.                 ReturnValue:=SELF.DoSendControlInfo (Input, Output, OutputSize, Result);
  255.             END;
  256.         SFindDItem:
  257.             BEGIN
  258.                 {$IFC qDebug}
  259.                     IF gVUDebug THEN
  260.                         WriteLn ('* SFindDItem');
  261.                 {$ENDC}
  262.             END;
  263.         SDItemInfo:
  264.             BEGIN
  265.                 ReturnValue:=SELF.DoSendDlogItemInfo (Input, Output, OutputSize, Result);
  266.             END;
  267.         OTHERWISE
  268.             BEGIN
  269.                 {$IFC qDebug}
  270.                     IF gVUDebug THEN
  271.                         WriteLn ('* ????????   Select=', Select);
  272.                 {$ENDC} 
  273.             END;
  274.     END; {case} 
  275.     MoleAssist:=integer(ReturnValue);
  276.     {$IFC qDebug}
  277.         IF gVUDebug THEN
  278.         BEGIN
  279.             Write ('Result=',integer(Result));
  280.             WriteLn ('     MoleAssist=',integer(ReturnValue));
  281.         END;
  282.     {$ENDC}
  283. END;
  284.  
  285.  
  286. {------------------------------------------------------------------------------------}
  287. { the routines for handling individual mole requests.  Each routine handles
  288.   exactly one mole request. }
  289.  
  290. { Handle a request for specific menu items.  The Mole can get info on menus in the
  291. menu bar, but we have to supply info on popup menus. }
  292. FUNCTION TVUAssist.DoMenuItems (Input :Ptr; Output :Ptr; VAR OutputSize :integer; 
  293.     Result :MoleError) :MoleError;
  294. VAR
  295.     MenuReqPtr        :SendMenuItemsParamsPtr;
  296.     MenuDescPtr        :MoleDataBlockPtr;
  297.     Popup            :TPopup;
  298. BEGIN
  299.     DoMenuItems:=Result; {initially, inherit result from mole}
  300.     MenuReqPtr:=SendMenuItemsParamsPtr(Input);
  301.     MenuDescPtr:=MoleDataBlockPtr(Output);
  302.     
  303.     { We don't need to respond when V.U. wants to find menus by rank (indicated by a menu_ID of 0).  
  304.     We do need to supply information about popups when the specified ID is non-zero. }
  305.     IF MenuReqPtr^.menu_ID<>0 THEN
  306.     BEGIN { find menu by menu ID }
  307.         IF (Result<>mNoErr) THEN
  308.         BEGIN
  309.             Popup:=SELF.MenuIDToPopup (MenuReqPtr^.menu_ID);
  310.             IF Popup<>NIL THEN
  311.             BEGIN
  312.                 DoMenuItems:=SELF.FillPopupItemDesc (Popup, RANK_OF_THE_INVISIBLE, 
  313.                     MenuReqPtr^.start_item, MenuReqPtr^.stop_item, MenuDescPtr, OutputSize);
  314.             END;
  315.         END;
  316.     END;
  317.     
  318.     {$IFC qDebug}
  319.         IF gVUDebug THEN
  320.         BEGIN
  321.             WriteLn ('SMenuItems');
  322.             SELF.PrintMenuItemReq (MenuReqPtr);
  323.             SELF.PrintMenuItemDesc (MenuDescPtr, OutputSize);
  324.         END;
  325.     {$ENDC}
  326. END;
  327.  
  328.  
  329. { Handle a request for menu info.  The Mole can get info on menus in the
  330. menu bar, but we have to supply info on popup menus. }
  331. FUNCTION TVUAssist.DoMenuInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer; 
  332.     Result :MoleError) :MoleError;
  333. VAR
  334.     MenuReqPtr        :SendMenuInfoParamsPtr;
  335.     MenuDescPtr        :MoleMenuInfoPtr;
  336.     Popup            :TPopup;
  337. BEGIN
  338.     DoMenuInfo:=Result; {initially, inherit result from mole}
  339.     MenuReqPtr:=SendMenuInfoParamsPtr(Input);
  340.     MenuDescPtr:=MoleMenuInfoPtr(Output);
  341.     
  342.     { We don't need to respond when V.U. wants to find menus by rank (indicated by a menu_ID of 0).  
  343.     We do need to supply information about popups when the specified ID is non-zero. }
  344.     IF MenuReqPtr^.menu_ID<>0 THEN
  345.     BEGIN { find menu by menu ID }
  346.         IF (Result<>mNoErr) THEN
  347.         BEGIN
  348.             Popup:=SELF.MenuIDToPopup (MenuReqPtr^.menu_ID);
  349.             IF Popup<>NIL THEN
  350.             BEGIN
  351.                 SELF.FillPopupDesc (Popup, RANK_OF_THE_INVISIBLE, MenuDescPtr, OutputSize);
  352.                 DoMenuInfo:=mNoErr;
  353.             END;
  354.         END;
  355.     END;
  356.     
  357.     {$IFC qDebug}
  358.         IF gVUDebug THEN
  359.         BEGIN
  360.             WriteLn ('SMenuInfo');
  361.             SELF.PrintMenuInfoReq (MenuReqPtr);
  362.             SELF.PrintMenuInfoDesc (MenuDescPtr);
  363.         END;
  364.     {$ENDC}
  365. END;
  366.  
  367.  
  368.  
  369. { Revise the values of the controlCount and numItems fields of the MoleWDescPtr, given
  370. knowledge of MacApp views. Also update validFlags and windowKind fields. WindowKind is set 
  371. to dialogKind so that V.U. will look for things that it can normally only see in dialogs 
  372. (such as icons and pictures) }
  373. FUNCTION TVUAssist.DoSendWindowInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  374.     Result :MoleError) :MoleError;
  375. VAR
  376.     WindReqPtr    :DWindReqPtr;
  377.     WindDescPtr    :MoleWDescPtr;
  378.     Window        :TWindow;
  379. BEGIN
  380.     DoSendWindowInfo:=Result; {initially, inherit result from mole}
  381.     WindReqPtr:=DWindReqPtr(Input);
  382.     WindDescPtr:=MoleWDescPtr(Output);
  383.     Window:=SELF.RankToWindow (WindReqPtr^);
  384.     IF Window<>NIL THEN 
  385.     BEGIN
  386.         WindDescPtr^.validFlags := BOR (WindDescPtr^.validFlags, VCTLCNT_MASK);
  387.         WindDescPtr^.validFlags := BOR (WindDescPtr^.validFlags, VITEMCNT_MASK);
  388.         WindDescPtr^.windowKind:=dialogKind;
  389.         WindDescPtr^.controlCount:=SELF.ViewCount (Window, false);
  390.         WindDescPtr^.numItems:=SELF.ViewCount (Window, true);
  391.         { OutputSize is filled in by the mole }
  392.         DoSendWindowInfo:=mNoErr;
  393.     END;
  394.     {$IFC qDebug}
  395.         IF gVUDebug THEN
  396.         BEGIN
  397.             WriteLn ('SWindInfo');
  398.             SELF.PrintWindReq (WindReqPtr);
  399.             SELF.PrintWindDesc (WindDescPtr);
  400.         END;
  401.     {$ENDC}
  402. END;
  403.  
  404.  
  405. { The mole sends us a point location in global coordinates.  We need to figure out
  406. which window and which control that point is in (if any), and send back info about
  407. that control. V.U. utilizes this routine for Control Manager controls (TCtlMgr) only.}
  408. FUNCTION TVUAssist.DoFindControl (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  409.     Result :MoleError) :MoleError;
  410. VAR
  411.     CtrlReqPtr    :SendFindControlParamPtr;
  412.     CtrlDescPtr    :MoleCDescPtr;
  413.     TargetPoint    :SendFindControlParam;
  414.     part        :integer;
  415.     wind        :WindowPeek;
  416.     SavePort    :GrafPtr;
  417.     Control        :TCtlMgr;
  418.     Rank        :integer;
  419.     SaveCtlList    :ControlHandle;
  420.     WhichCtl    :ControlHandle;
  421.     Window        :TWindow;
  422.     VPt            :VPoint;
  423. BEGIN
  424.     DoFindControl:=Result; {initially, inherit result from mole}
  425.     CtrlReqPtr:=SendFindControlParamPtr(Input);
  426.     TargetPoint:=CtrlReqPtr^;
  427.     CtrlDescPtr:=MoleCDescPtr(Output);
  428.  
  429.     part:=FindWindow (TargetPoint, WindowPtr(wind));
  430.     { The mole also tests for part=inSysWindow, but we'll let the mole handle those cases}
  431.     IF (wind<>NIL) AND (part=inContent) THEN
  432.     BEGIN
  433.         Window:=gApplication.WMgrToWindow(WindowPtr(wind));
  434.         IF (Window<>NIL) THEN
  435.         BEGIN
  436.             Control:=SELF.PointToControl (Window, TargetPoint, Rank);
  437.             IF Control<>NIL THEN
  438.             BEGIN
  439.                 part:=-1;
  440.                 { Get the control part code.  Controls are not kept in the controllist,
  441.                 so we temporarily put them in there.  Also, they are in their subviews
  442.                 local coordinate system, so we must convert targetpoint. }
  443.                 GetPort (SavePort);
  444.                 SetPort (WindowPtr(wind));
  445.                 IF Window.Focus THEN
  446.                 BEGIN
  447.                     SaveCtlList:=wind^.controlList;
  448.                     wind^.controlList:=Control.fCMgrControl;
  449.                     SELF.GlobalToWindow (Window, TargetPoint, VPt);
  450.                     SELF.WindowToView (Control, VPt, TargetPoint);
  451.                     part:=FindControl (TargetPoint, WindowPtr(wind), WhichCtl);
  452.                     wind^.controlList:=SaveCtlList;
  453.                 END;
  454.                 SetPort (SavePort);
  455.                 
  456.                 IF (SELF.FillCtrlDesc (CtrlDescPtr, part, SELF.WindowToRank(wind), 
  457.                     Rank, Control, OutputSize)) THEN
  458.                 BEGIN
  459.                     DoFindControl:=mNoErr;
  460.                 END;
  461.             END;
  462.         END;
  463.     END;
  464.     {$IFC qDebug}
  465.         IF gVUDebug THEN
  466.             BEGIN
  467.                 WriteLn ('SFindCtl');
  468.                 SELF.PrintCtrlPoint (CtrlReqPtr);
  469.                 SELF.PrintCtrlDesc (CtrlDescPtr); 
  470.             END;
  471.     {$ENDC}
  472. END;
  473.  
  474.  
  475. { Read the input parameter to see which control V.U. wants info on, then
  476. fill in the SendCtlInfoParamsPtr record.  The mole can't gather any info about
  477. MacApp controls without our help, so we fill in the whole record, except for part, 
  478. which doesn't apply.}
  479. FUNCTION TVUAssist.DoSendControlInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  480.     Result :MoleError) :MoleError;
  481. VAR
  482.     CtrlReqPtr    :SendCtlInfoParamsPtr;
  483.     CtrlDescPtr    :MoleCDescPtr;
  484.     Window        :TWindow;
  485.     Control        :TControl;
  486.     gridItem    :TGridItem;
  487. BEGIN
  488.     DoSendControlInfo:=Result; {initially, inherit result from mole}
  489.     gridItem:=NIL;
  490.     CtrlReqPtr:=SendCtlInfoParamsPtr(Input);
  491.     CtrlDescPtr:=MoleCDescPtr(Output);
  492.  
  493.     Window:=SELF.RankToWindow (CtrlReqPtr^.window_rank);
  494.     IF Window<>NIL THEN
  495.     BEGIN
  496.         Control:=TControl(SELF.RankToItem (Window, CtrlReqPtr^.control_rank, false, gridItem));
  497.         IF Control<>NIL THEN
  498.         BEGIN
  499.             IF (SELF.FillCtrlDesc (CtrlDescPtr, -1, CtrlReqPtr^.window_rank, 
  500.                 CtrlReqPtr^.control_rank, Control, OutputSize)) THEN
  501.             BEGIN
  502.                 DoSendControlInfo:=mNoErr;
  503.             END;
  504.         END;
  505.     END;
  506.     
  507.     {$IFC qDebug}
  508.         IF gVUDebug THEN
  509.         BEGIN
  510.             WriteLn ('SCtlInfo');
  511.             SELF.PrintCtrlReq (CtrlReqPtr);
  512.             SELF.PrintCtrlDesc (CtrlDescPtr);
  513.         END;
  514.     {$ENDC}
  515. END;
  516.  
  517.  
  518. { Read the input to see which dialog item in which window V.U. wants data on, and
  519. fill in the dialogiteminfo record. }
  520. FUNCTION TVUAssist.DoSendDlogItemInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  521.     Result :MoleError) :MoleError;
  522. VAR
  523.     DlogReqPtr    :SendDItemInfoPtr;
  524.     DlogDescPtr    :MoleDItemInfoPtr;
  525.     Window        :TWindow;
  526.     View        :TView;
  527.     gridItem    :TGridItem;
  528. BEGIN
  529.     DoSendDlogItemInfo:=Result; {initially, inherit result from mole}
  530.     gridItem:=NIL;
  531.     DlogReqPtr:=SendDItemInfoPtr(Input);
  532.     DlogDescPtr:=MoleDItemInfoPtr(Output);
  533.     
  534.     Window:=SELF.RankToWindow (DlogReqPtr^.window_rank);
  535.     IF Window<>NIL THEN
  536.     BEGIN
  537.         View:=SELF.RankToItem (Window, DlogReqPtr^.item_num, true, gridItem);
  538.         IF View<>NIL THEN
  539.         BEGIN
  540.             SELF.FillDlogItemDesc (DlogDescPtr, Window, DlogReqPtr^.window_rank, 
  541.                 DlogReqPtr^.item_num, View, OutputSize, gridItem);
  542.             DoSendDlogItemInfo:=mNoErr;
  543.         END;
  544.     END;
  545.  
  546.     {$IFC qDebug}
  547.         IF gVUDebug THEN
  548.             BEGIN
  549.                 WriteLn ('SDItemInfo');
  550.                 SELF.PrintDlogReq (DlogReqPtr);
  551.                 SELF.PrintDlogDesc (DlogDescPtr);
  552.             END;
  553.     {$ENDC}
  554. END;
  555.  
  556.  
  557. {------------------------------------------------------------------------------------}
  558. { routines for filling in mole data structures }
  559.  
  560. { Given a TPopup object, fill in the mole's menu descriptor record. }
  561. PROCEDURE TVUAssist.FillPopupDesc (Popup: TPopup; MenuRank: integer; 
  562.     MenuDescPtr :MoleMenuInfoPtr; VAR OutputSize :integer);
  563. BEGIN
  564.     WITH MenuDescPtr^ DO
  565.     BEGIN
  566.         num_items:=CountMItems (Popup.fMenuHandle);
  567.         rank:=MenuRank;
  568.         left_edge:=0;
  569.         menuID:=Popup.fMenuID;
  570.         menuWidth:=Popup.fMenuHandle^^.menuWidth;
  571.         menuHeight:=Popup.fMenuHandle^^.menuHeight;
  572.         enableFlags:=Popup.fMenuHandle^^.enableFlags;
  573.         text_name:=Popup.fMenuHandle^^.menuData;
  574.         
  575.         { this ugly thing computes the length (bytes used) of MoleMenuInfo }
  576.         OutputSize:=sizeof(MoleMenuInfo) - (255-length(text_name));
  577.     END;
  578. END;
  579.  
  580.  
  581. { Given a TPopup object, fill in the mole's menuitem descriptor record. }
  582. FUNCTION TVUAssist.FillPopupItemDesc (Popup: TPopup; MenuRank: integer; start: integer; 
  583.     stop: integer; MenuItemDescPtr :MoleDataBlockPtr; VAR OutputSize :integer) :MoleError;
  584.     
  585.     { this function depends upon Ptr being a pointer to a single byte }
  586.     FUNCTION SeekMenuItem (ItemNum: integer; MenuHdl: MenuHandle) :Ptr;
  587.     VAR
  588.         SeekPtr    :Ptr;
  589.         SeekNum    :integer;
  590.     BEGIN
  591.         SeekNum:=1;
  592.         SeekPtr:= Ptr(ORD4(@MenuHdl^^.menuData) + length(MenuHdl^^.menuData) + 1);
  593.         WHILE (SeekNum<ItemNum) AND (SeekPtr^<>0) DO
  594.         BEGIN
  595.             SeekPtr:= Ptr(ORD4(SeekPtr) + SeekPtr^ + ADDITIONAL_MENU_ITEM_DATA);
  596.             SeekNum:=SeekNum+1;
  597.         END;
  598.         SeekMenuItem:=SeekPtr;
  599.     END;
  600.     
  601. VAR
  602.     StartPtr    :Ptr;
  603.     StopPtr        :Ptr;
  604. BEGIN
  605.     FillPopupItemDesc:=mNoErr;
  606.     
  607.     IF (start>CountMItems (Popup.fMenuHandle)) OR (start<1) THEN
  608.     BEGIN
  609.         FillPopupItemDesc:=mBadMenuItemIndex;
  610.         EXIT (FillPopupItemDesc);
  611.     END;
  612.     
  613.     IF stop>CountMItems (Popup.fMenuHandle) THEN
  614.     BEGIN
  615.         stop:=CountMItems (Popup.fMenuHandle);
  616.         FillPopupItemDesc:=mBadLastMenuItemIndex;
  617.     END;
  618.     
  619.     StartPtr:=SeekMenuItem (start, Popup.fMenuHandle);
  620.     StopPtr:=SeekMenuItem (stop+1, Popup.fMenuHandle);
  621.     IF (StartPtr=NIL) OR (StopPtr=NIL) THEN
  622.     BEGIN
  623.         FillPopupItemDesc:=mBadMenuItemIndex;
  624.         EXIT (FillPopupItemDesc);
  625.     END;
  626.     MenuItemDescPtr^.blockLength:=stop-start+1;
  627.     BlockMove (StartPtr, @MenuItemDescPtr^.dataBlock[0], ORD4(StopPtr)-ORD4(StartPtr));
  628.     
  629.     { this ugly thing computes the length (bytes used) of MoleDataBlock }
  630.     OutputSize:=sizeof(integer) + (ORD4(StopPtr)-ORD4(StartPtr));
  631. END;
  632.  
  633.  
  634. { Fill in a mole control descriptor record.  Valid descendants of TControl are descendants of
  635. TCtlMgr and TPopup. Will return false if TControl is not a descendant of TCtlMgr or TPopup.}
  636. FUNCTION TVUAssist.FillCtrlDesc (CtrlDescPtr :MoleCDescPtr; thePart :integer; 
  637.     WindRank :integer; ControlRank :integer; Control :TControl; VAR OutputSize :integer): BOOLEAN;
  638. VAR
  639.     dummy        :longint;
  640.     ControlHdl    :ControlHandle;
  641.     aVRect        :VRect;
  642. BEGIN
  643.     FillCtrlDesc:=FALSE; 
  644.     IF Member (Control, TCtlMgr) THEN
  645.     BEGIN
  646.         ControlHdl:=TCtlMgr(Control).fCMgrControl;
  647.         WITH CtrlDescPtr^, ControlHdl^^ DO
  648.         BEGIN
  649.             validFlags:=VALL_C_MASK;
  650.             IF thePart=-1 THEN
  651.             BEGIN
  652.                 dummy:=validFlags;
  653.                 BClr (dummy, VCPART);
  654.                 validFlags:=dummy;
  655.             END;
  656.             owner_rank:=WindRank;
  657.             ctlRect:=contrlRect;
  658.             SELF.ViewRectToWindowRect (ctlRect, Control);
  659.             ctlValue:=contrlValue;
  660.             ctlMin:=contrlMin;
  661.             ctlMax:=contrlMax;
  662.             ctlHilite:=contrlHilite;
  663.             IF thePart=-1 THEN
  664.                 part:=0
  665.             ELSE
  666.                 part:=thePart;
  667.             ctlRank:=ControlRank;
  668.             ctlDefID:=BAND(BSR(longint(contrlDefProc), 24), $7);
  669.             IF Member (Control, TScrollBar) THEN
  670.                 ctlDefID:=ctlDefID+16;
  671.             popupMenuID:=0;
  672.             text_name:=contrlTitle;
  673.     
  674.             { this ugly thing computes the length (bytes used) of CtrlDescPtr }
  675.             OutputSize:=sizeof(MoleControlDescriptor) - (255-length(text_name));
  676.             FillCtrlDesc:=TRUE;
  677.         END;
  678.     END
  679.     ELSE
  680.     IF Member (Control, TPopup) THEN
  681.     BEGIN
  682.         WITH CtrlDescPtr^ DO
  683.         BEGIN
  684.             validFlags:=VALL_C_MASK;
  685.             IF thePart=-1 THEN
  686.             BEGIN
  687.                 dummy:=validFlags;
  688.                 BClr (dummy, VCPART);
  689.                 validFlags:=dummy;
  690.             END;
  691.             owner_rank:=WindRank;
  692.             Control.GetExtent (aVRect);
  693.             VRectToRect(aVRect, ctlRect);
  694.             SELF.ViewRectToWindowRect (ctlRect, Control);
  695.  
  696.             ctlValue:=TPopup(Control).GetCurrentItem;
  697.             ctlMin:=1;
  698.             ctlMax:=CountMItems(TPopup(Control).fMenuHandle);
  699.             ctlHilite:=0;
  700.             IF thePart=-1 THEN
  701.                 part:=0
  702.             ELSE
  703.                 part:=thePart;
  704.             ctlRank:=ControlRank;
  705.             ctlDefID:=POPUP_CDEF*16;
  706.             popupMenuID:=TPopup(Control).fMenuID;
  707.             text_name:=TPopup(Control).fMenuHandle^^.menuData;
  708.     
  709.             { this ugly thing computes the length (bytes used) of CtrlDescPtr }
  710.             OutputSize:=sizeof(MoleControlDescriptor) - (255-length(text_name));
  711.             FillCtrlDesc:=TRUE;
  712.         END;
  713.     END;
  714. END;
  715.  
  716.  
  717. PROCEDURE TVUAssist.ViewRectToWindowRect (VAR aRect :Rect; aView :TView);
  718. VAR
  719.     VPt :VPoint;
  720. BEGIN
  721.     PtToVPt(aRect.topLeft, VPt);
  722.     aView.LocalToWindow (VPt);
  723.     aRect.topLeft:=VPtToPt (VPt);
  724.     PtToVPt(aRect.botRight, VPt);
  725.     aView.LocalToWindow (VPt);
  726.     aRect.botRight:=VPtToPt (VPt);
  727. END;
  728.  
  729.  
  730. { Fill in a mole dialog item descriptor record }
  731. PROCEDURE TVUAssist.FillDlogItemDesc (DlogDescPtr :MoleDItemInfoPtr; Window :TWindow;
  732.     WindRank :integer; ItemRank :integer; Item :TView; VAR OutputSize :integer; gridItem :TGridItem);
  733. VAR
  734.     aVRect        :VRect;
  735.     TextLen     :longint;
  736.     TextHdl     :Handle;
  737.     ItemKind    :ViewItems;
  738.     aCell        :GridCell;
  739. BEGIN
  740.     WITH DlogDescPtr^ DO
  741.     BEGIN
  742.         ItemKind:=SELF.GetItemType (Item, true, true);
  743.         { fill in box, itemType, item_enabled, has_text and text_name here }
  744.         CASE ItemKind OF
  745.             VINotMember:
  746.                 ;
  747.             VIButton:
  748.             BEGIN
  749.                 TCtlMgr(Item).ControlArea (box);
  750.                 itemType:=btnCtrlItem;
  751.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsViewEnabled;
  752.                 has_text:=TRUE;
  753.                 TCtlMgr(Item).GetText (text_name);
  754.             END;
  755.             VIRadio:
  756.             BEGIN
  757.                 TCtlMgr(Item).ControlArea (box);
  758.                 itemType:=radCtrlItem;
  759.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsViewEnabled;
  760.                 has_text:=TRUE;
  761.                 TCtlMgr(Item).GetText (text_name);
  762.             END;
  763.             VICheckBox:
  764.             BEGIN
  765.                 TCtlMgr(Item).ControlArea (box);
  766.                 itemType:=chkCtrlItem;
  767.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsViewEnabled;
  768.                 has_text:=TRUE;
  769.                 TCtlMgr(Item).GetText (text_name);
  770.             END;
  771.             VIScrollBar:
  772.             BEGIN
  773.                 TCtlMgr(Item).ControlArea (box);
  774.                 itemType:=resCtrlItem;
  775.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsViewEnabled;
  776.                 has_text:=TRUE;
  777.                 TCtlMgr(Item).GetText (text_name);
  778.             END;
  779.             VIStatText:
  780.             BEGIN
  781.                 Item.GetExtent (aVRect);
  782.                 VRectToRect(aVRect, box);
  783.                 itemType:=statText;
  784.                 item_enabled:=FALSE;
  785.                 has_text:=TRUE;
  786.                 TStaticText(Item).GetText (text_name);
  787.             END;
  788.             VIEditText:
  789.             BEGIN
  790.                 Item.GetExtent (aVRect);
  791.                 VRectToRect(aVRect, box);
  792.                 itemType:=editText;
  793.                 item_enabled:=Item.IsViewEnabled;
  794.                 has_text:=TRUE;
  795.                 TStaticText(Item).GetText (text_name);
  796.             END;
  797.             VIIcon:
  798.             BEGIN
  799.                 Item.GetExtent (aVRect);
  800.                 VRectToRect(aVRect, box);
  801.                 itemType:=iconItem;
  802.                 item_enabled:=Item.IsViewEnabled;
  803.                 has_text:=FALSE;
  804.                 item_text_ptr:=NIL;
  805.             END;
  806.             VIPopup:
  807.             BEGIN
  808.                 Item.GetExtent (aVRect);
  809.                 VRectToRect(aVRect, box);
  810.                 itemType:=resCtrlItem;
  811.                 item_enabled:=Item.IsViewEnabled;
  812.                 has_text:=FALSE;
  813.                 item_text_ptr:=NIL;
  814.             END;
  815.             VIPicture:
  816.             BEGIN
  817.                 Item.GetExtent (aVRect);
  818.                 VRectToRect(aVRect, box);
  819.                 itemType:=picItem;
  820.                 item_enabled:=Item.IsViewEnabled;
  821.                 has_text:=FALSE;
  822.                 item_text_ptr:=NIL;
  823.             END;
  824.             VITextEdit:
  825.             BEGIN
  826.                 Item.GetExtent (aVRect);
  827.                 VRectToRect(aVRect, box);
  828.                 itemType:=editText;
  829.                 item_enabled:=Item.IsViewEnabled;
  830.                 has_text:=TRUE;
  831.                 TextHdl:=TTEView(Item).ExtractText;
  832.                 TextLen:=GetHandleSize (TextHdl);
  833.                 IF TextLen>255 THEN TextLen:=255;
  834.                 BlockMove (TextHdl^, @text_name, TextLen);
  835.             END;
  836.             VIGridItem:
  837.             BEGIN
  838.                 gridItem.GetExtent (aVRect);
  839.                 VRectToRect(aVRect, box);
  840.                 itemType:=CUSTOM_ITEM;
  841.                 item_enabled:=gridItem.fGridView.IsViewEnabled;
  842.                 IF Member (Item, TTextGridView) THEN
  843.                 BEGIN  {item has text associated with it}
  844.                     has_text:=TRUE;
  845.                     aCell.v:=gridItem.fRow;
  846.                     aCell.h:=gridItem.fColumn;
  847.                     TTextGridView(gridItem.fGridView).GetText (aCell, text_name);
  848.                 END
  849.                 ELSE   {item may not have text associated with it}
  850.                 BEGIN
  851.                     has_text:=FALSE;
  852.                     item_text_ptr:=NIL;
  853.                 END;
  854.             END;
  855.         END; { case }
  856.         SELF.ViewRectToWindowRect (box, Item);
  857.         { fill in ctlRank, owner_rank, and item_num here }
  858.         ctlRank:=SELF.ItemToRank (Window, Item, false);
  859.         owner_rank:=WindRank;
  860.         item_num:=ItemRank;
  861.             
  862.         { this ugly thing computes the length (bytes used) of MoleDItemInfo }
  863.         IF ItemKind<>VINotMember THEN
  864.             OutputSize:=sizeof(MoleDItemInfo) - (255-length(text_name));
  865.         
  866.         IF gridItem <> NIL THEN
  867.             gridItem.Free;
  868.     END; { with }
  869. END;
  870.  
  871.  
  872. {------------------------------------------------------------------------------------}
  873. { routines for searching through the view tree to find particular views }
  874.  
  875.  
  876. { Given a Window Manager window pointer, try to find the corresponding TWindow object.
  877. Note that there is a TApplication method, WMgrToWindow, which does this, but it crashes
  878. a Mac Plus in certain cases.}
  879. FUNCTION TVUAssist.MyWMgrToWindow(wMgrWindow: WindowPtr) :TWindow;
  880. VAR
  881.     foundWindow: TWindow;
  882.  
  883.     PROCEDURE CheckForWMgrWind(aWindow: TWindow);
  884.     BEGIN
  885.         IF (aWindow.fWMgrWindow = wMgrWindow) THEN
  886.         BEGIN
  887.             foundWindow:=aWindow;
  888.         END;
  889.     END;
  890.  
  891. BEGIN    
  892.     foundWindow:=NIL;
  893.     gApplication.ForAllWindowsDo(CheckForWMgrWind);
  894.     MyWMgrToWindow:=foundWindow;
  895. END;
  896.  
  897.  
  898.  
  899. { Given the rank (z-order) of a window, return the window object.  Invisible
  900. windows are not considered to be in the window list, for ranking purposes. }
  901. FUNCTION TVUAssist.RankToWindow (Rank :integer) :TWindow;
  902. VAR
  903.     i: integer;
  904.     Window :WindowPeek;
  905. BEGIN
  906.     RankToWindow:=NIL;
  907.     i:=1;
  908.     Window:=WindowPeek(FrontWindow);
  909.     WHILE Window<>NIL DO
  910.     BEGIN
  911.         IF Window^.visible THEN
  912.         BEGIN
  913.             IF i=Rank THEN
  914.             BEGIN
  915.                 RankToWindow:=SELF.MyWMgrToWindow(WindowPtr(Window));
  916.                 LEAVE;
  917.             END;
  918.             i:=i+1;
  919.         END;
  920.         Window:=Window^.nextWindow;
  921.     END;
  922. END;
  923.  
  924.  
  925. {Given a window ptr, return the window's rank (z-order).}
  926. FUNCTION TVUAssist.WindowToRank (WindToFind :WindowPeek) :integer;
  927. VAR
  928.     i: integer;
  929.     Window :WindowPeek;
  930. BEGIN
  931.     WindowToRank:=0;
  932.     i:=1;
  933.     Window:=WindowPeek(FrontWindow);
  934.     WHILE Window<>NIL DO
  935.     BEGIN
  936.         IF Window^.visible THEN
  937.         BEGIN
  938.             IF WindToFind=Window THEN
  939.             BEGIN
  940.                 WindowToRank:=i;
  941.                 LEAVE;
  942.             END;
  943.             i:=i+1;
  944.         END;
  945.         Window:=Window^.nextWindow;
  946.     END;
  947. END;
  948.  
  949.  
  950. { Convert a point in global coordinates to window coordinates. }
  951. PROCEDURE TVUAssist.GlobalToWindow (Window :TWindow; Pt :Point; VAR VPt :VPoint);
  952. VAR
  953.     SavePort    :GrafPtr;
  954.     TargetPoint    :Point;
  955. BEGIN
  956.     VPt.h:=0;
  957.     VPt.v:=0;
  958.     GetPort (SavePort);
  959.     SetPort (Window.GetGrafPort);
  960.     IF Window.Focus THEN
  961.     BEGIN
  962.         TargetPoint:=Pt;
  963.         GlobalToLocal (TargetPoint);
  964.         Window.QDToViewPt(TargetPoint, VPt);
  965.     END;
  966.     SetPort (SavePort);
  967. END;
  968.  
  969.  
  970. { Convert a point in window coordinates to a subview's coordinates. Return both a
  971. VPoint and a QDPoint. }
  972. PROCEDURE TVUAssist.WindowToView (View :TView; VAR VPt :VPoint; VAR Pt :Point);
  973. BEGIN
  974.     Pt.h:=0;
  975.     Pt.v:=0;
  976.     View.WindowToLocal(VPt);
  977.     IF View.Focus THEN
  978.         Pt:=View.ViewToQDPt (VPt);
  979. END;
  980.  
  981.  
  982.  
  983. { In the front (active) window, given the menu ID of a popup item, return the  
  984. popup menu object and its rank. }
  985. FUNCTION TVUAssist.MenuIDToPopup (MenuID :integer) :TPopup;
  986. VAR
  987.     foundView     :TView;
  988.     dummyView    :TView;
  989.     window        :TWindow;
  990.     
  991.     FUNCTION TestSubID(theSubView: TView): BOOLEAN;
  992.     BEGIN
  993.         IF theSubView.IsShown THEN
  994.         BEGIN    
  995.             IF SELF.GetItemType (theSubView, false, false)=VIPopup THEN
  996.             BEGIN
  997.                 IF TPopup(theSubView).fMenuID=MenuID THEN
  998.                     foundView:=theSubView;
  999.             END;
  1000.             IF (foundView=NIL) THEN
  1001.                 dummyView:=theSubView.FirstSubViewThat (TestSubID);
  1002.         END;
  1003.         TestSubID:=foundView <> NIL;
  1004.     END;
  1005.     
  1006. BEGIN
  1007.     foundView:=NIL;
  1008.     window:=gApplication.GetActiveWindow;
  1009.     IF (Window<>NIL) & (Window.IsShown) THEN
  1010.         dummyView:=Window.FirstSubViewThat (TestSubID);
  1011.     MenuIDToPopup:=TPopup(foundView);
  1012. END;
  1013.  
  1014.  
  1015. { Given a window object and a point in global coordinates,
  1016. find the control which is under that point. Only descendants of
  1017. TCtlMgr are considered.}
  1018. FUNCTION TVUAssist.PointToControl (Window :TWindow; Pt :Point; VAR Rank :integer) :TCtlMgr;
  1019. VAR
  1020.     foundView     : TView;
  1021.     dummyView    : TView;
  1022.     VPt            : VPoint;
  1023.     TestPoint    : VPoint;
  1024.     DummyPoint    : Point;
  1025.     aRect        : Rect;
  1026.     
  1027.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  1028.     VAR
  1029.         ItemType :ViewItems;
  1030.     BEGIN
  1031.         IF theSubView.IsShown THEN
  1032.         BEGIN    
  1033.             IF Member (theSubView, TCtlMgr) THEN
  1034.             BEGIN
  1035.                 TestPoint:=VPt;
  1036.                 SELF.WindowToView (theSubView, TestPoint, DummyPoint);
  1037.                 IF theSubView.ContainsMouse(TestPoint) THEN
  1038.                     foundView:=theSubView;
  1039.             END;
  1040.             IF (foundView=NIL) THEN
  1041.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  1042.         END;
  1043.         TestSubView:=foundView <> NIL;
  1044.     END;
  1045.     
  1046. BEGIN
  1047.     foundView:=NIL;
  1048.     SELF.GlobalToWindow (Window, Pt, VPt);
  1049.     IF Window.IsShown THEN
  1050.         dummyView:=Window.FirstSubViewThat (TestSubView);
  1051.     Rank:=SELF.ItemToRank (Window, foundView, false);
  1052.     PointToControl:=TCtlMgr(foundView);
  1053. END;
  1054.  
  1055.  
  1056. { Walk the view hierarchy tree, counting the number of user interface items.
  1057. Only visible views and items are counted. }
  1058. FUNCTION TVUAssist.ViewCount (Window :TWindow; DlogViewItems :Boolean) :integer;
  1059. VAR
  1060.     ItemCount :integer;
  1061.     
  1062.     PROCEDURE DoToSubView(theSubView: TView);
  1063.     VAR
  1064.         ItemType: ViewItems;
  1065.     BEGIN
  1066.         IF theSubView.IsShown THEN
  1067.         BEGIN
  1068.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  1069.             IF ItemType<>VINotMember THEN
  1070.             BEGIN
  1071.                 IF ItemType=VIGridItem THEN
  1072.                     ItemCount:=ItemCount+SELF.CountGridItems (TGridView(theSubView))
  1073.                 ELSE
  1074.                     ItemCount := ItemCount + 1;
  1075.             END;
  1076.             IF Member (theSubView, TView) THEN
  1077.                 theSubView.EachSubView (DoToSubView);
  1078.         END;
  1079.     END;
  1080.     
  1081. BEGIN
  1082.     ItemCount:=0;
  1083.     IF Window.IsShown THEN
  1084.         Window.EachSubView (DoToSubView);
  1085.     ViewCount:=ItemCount;
  1086. END;
  1087.  
  1088.  
  1089. {Given a control or dialog item (View), and the window its in (Window), return its rank. }
  1090. FUNCTION TVUAssist.ItemToRank (Window :TWindow; View :TView; DlogViewItems :Boolean) :integer;
  1091. VAR
  1092.     ItemCount    :integer;
  1093.     Rank         :integer;
  1094.     dummyView    :TView;
  1095.     
  1096.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  1097.     VAR
  1098.         ItemType:    ViewItems;
  1099.     BEGIN
  1100.         IF theSubView.IsShown THEN
  1101.         BEGIN    
  1102.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  1103.             IF ItemType<>VINotMember THEN
  1104.             BEGIN
  1105.                 IF ItemType=VIGridItem THEN
  1106.                 BEGIN
  1107.                     IF (Member(View, TGridItem)) & (theSubView=TGridItem(View).fGridView) THEN
  1108.                         Rank:=ItemCount+TGridItem(View).fRank
  1109.                     ELSE
  1110.                         ItemCount:=ItemCount+SELF.CountGridItems (TGridView(theSubView));
  1111.                 END
  1112.                 ELSE BEGIN
  1113.                     ItemCount := ItemCount + 1;
  1114.                     IF theSubView=View THEN
  1115.                         Rank:=ItemCount;
  1116.                 END;
  1117.             END;
  1118.             IF (Rank=0) THEN
  1119.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  1120.         END;
  1121.         TestSubView:=Rank <> 0;
  1122.     END;
  1123.     
  1124. BEGIN
  1125.     Rank:=0;    
  1126.     ItemCount:=0;
  1127.     IF Window.IsShown THEN
  1128.         dummyView:=Window.FirstSubViewThat (TestSubView);
  1129.     ItemToRank:=Rank;
  1130. END;
  1131.  
  1132.  
  1133. { Given a window object and the rank (z-order) of an item, return the item object. If
  1134. the item is a cell of a TGridView object, return that object in gridItem.}
  1135. FUNCTION TVUAssist.RankToItem (Window :TWindow; Rank :integer; DlogViewItems :Boolean;
  1136.                                VAR gridItem: TGridItem) :TView;
  1137. VAR
  1138.     ItemCount    :integer;
  1139.     foundView     :TView;
  1140.     dummyView    :TView;
  1141.     
  1142.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  1143.     VAR
  1144.         ItemType:    ViewItems;
  1145.         GridCount:    integer;
  1146.     BEGIN
  1147.         IF theSubView.IsShown THEN
  1148.         BEGIN    
  1149.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  1150.             IF ItemType<>VINotMember THEN
  1151.             BEGIN
  1152.                 IF (ItemType=VIGridItem) THEN
  1153.                 BEGIN
  1154.                     GridCount:=SELF.CountGridItems (TGridView(theSubView));
  1155.                     IF (Rank>ItemCount) AND (Rank<=ItemCount+GridCount) THEN
  1156.                     BEGIN
  1157.                         New (gridItem);
  1158.                         FailNil (gridItem);
  1159.                         gridItem.IGridItem (TGridView(theSubView), Rank-ItemCount);
  1160.                         foundView:=theSubView;
  1161.                     END;
  1162.                     ItemCount := ItemCount + GridCount;
  1163.                 END
  1164.                 ELSE BEGIN
  1165.                     ItemCount := ItemCount + 1;
  1166.                     IF ItemCount=Rank THEN
  1167.                         foundView:=theSubView;
  1168.                 END;
  1169.             END;
  1170.             IF (foundView=NIL) THEN
  1171.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  1172.         END;
  1173.     TestSubView:=foundView <> NIL;
  1174.     END;
  1175.     
  1176. BEGIN
  1177.     foundView:=NIL;
  1178.     ItemCount:=0;
  1179.     IF Window.IsShown THEN
  1180.         dummyView:=Window.FirstSubViewThat (TestSubView);
  1181.     RankToItem:=foundView;
  1182. END;
  1183.  
  1184.  
  1185. { Report the number of items in a TGridView.  This is here so it can
  1186. be easily overridden if you only want rows or columns to show up as
  1187. seperate user interface items, instead of each cell. }
  1188. FUNCTION TVUAssist.CountGridItems (theGridView: TGridView): integer;
  1189. BEGIN
  1190.     CountGridItems:=theGridView.fNumOfRows*theGridView.fNumOfCols;
  1191. END;
  1192.  
  1193.  
  1194.  
  1195. {Given a view item and the control/dialog item flag, decide if this
  1196. view object is a control if the flag=ControlsOnly, or if its a dialog
  1197. item if the flag=DialogItems, or if its neither.  Of course, MacApp 
  1198. doesn't have a concept of dialog items, so we improvise.  Here are the criteria.
  1199. Any descendent of TCtlMgr is a control.  Descendants of TPopup are also classified
  1200. as contols because V.U. can normally only deal with popups which utilize the popup
  1201. CDEF.  So V.U. expects popups to be controls.
  1202.  
  1203. Descendents of TTEView and some descendants of TControl (specifically TEditText, 
  1204. TStaticText, TIcon, TPicture, and TGridView) are considered to be DialogItems for V.U.'s sake.  
  1205. GridViewItems are considered along with other DlogViewItems only if GridViewItems parameter 
  1206. is true.}
  1207. FUNCTION TVUAssist.GetItemType (Item :TView; DlogViewItems :Boolean;
  1208.     GridViewItems: Boolean) :ViewItems;
  1209. BEGIN
  1210.     GetItemType:=VINotMember;
  1211.     IF Member (Item, TButton) THEN
  1212.         GetItemType:=VIButton
  1213.     ELSE IF Member (Item, TRadio) THEN
  1214.         GetItemType:=VIRadio
  1215.     ELSE IF Member (Item, TCheckBox) THEN
  1216.         GetItemType:=VICheckBox
  1217.     ELSE IF Member (Item, TScrollBar) THEN
  1218.         GetItemType:=VIScrollBar
  1219.     ELSE IF Member (Item, TPopup) THEN    
  1220.         GetItemType:=VIPopup;            
  1221.     IF DlogViewItems THEN                
  1222.     BEGIN
  1223.         IF Member (Item, TEditText) THEN    {TEditText descends from TStaticText}
  1224.             GetItemType:=VIEditText
  1225.         ELSE IF Member (Item, TStaticText) THEN
  1226.             GetItemType:=VIStatText
  1227.         ELSE IF Member (Item, TIcon) THEN
  1228.             GetItemType:=VIIcon
  1229.         ELSE IF Member (Item, TPicture) THEN
  1230.             GetItemType:=VIPicture
  1231.         ELSE IF Member (Item, TTEView) AND NOT Member (Item, TDialogTEView) THEN
  1232.             GetItemType:=VITextEdit;
  1233.         IF (fGridItemSupport AND GridViewItems) THEN
  1234.         BEGIN 
  1235.             IF Member (Item, TGridView) THEN 
  1236.             BEGIN                                                     
  1237.                 GetItemType:=VIGridItem;
  1238.             END;
  1239.         END;
  1240.     END;
  1241.     
  1242. END;
  1243.  
  1244.  
  1245. {------------------------------------------------------------------------------------}
  1246. { debugging routines which print the contents of various mole data structures  
  1247.   You may wish to remove the debugging routines.
  1248. }
  1249.  
  1250. {$IFC qDebug}
  1251. PROCEDURE TVUAssist.PrintFindWindReq (WindReqPtr :SendFindWindowParamPtr);
  1252. BEGIN
  1253.     WriteLn ('WindReqPtr^=',WindReqPtr^.h, WindReqPtr^.v);
  1254. END;
  1255. {$ENDC}
  1256.  
  1257. {$IFC qDebug}
  1258. PROCEDURE TVUAssist.PrintWindReq (WindReqPtr :DWindReqPtr);
  1259. BEGIN
  1260.     WriteLn ('WindReqPtr^=',WindReqPtr^);
  1261. END;
  1262. {$ENDC}
  1263.  
  1264. {$IFC qDebug}
  1265. PROCEDURE TVUAssist.PrintWindDesc (WindDescPtr :MoleWDescPtr);
  1266. BEGIN
  1267.     Write ('WindDescPtr^validFlags=');
  1268.     WriteHexInt (WindDescPtr^.validFlags);
  1269.     WriteLn;
  1270.     WriteLn ('WindDescPtr^windowKind=',WindDescPtr^.windowKind);
  1271.     WriteLn ('WindDescPtr^portRect=',WindDescPtr^.portRect.top,
  1272.         WindDescPtr^.portRect.left, WindDescPtr^.portRect.bottom,
  1273.         WindDescPtr^.portRect.right);
  1274.     WriteLn ('WindDescPtr^structRect=',WindDescPtr^.structRect.top,
  1275.         WindDescPtr^.structRect.left, WindDescPtr^.structRect.bottom,
  1276.         WindDescPtr^.structRect.right);
  1277.     WriteLn ('WindDescPtr^contentRect=',WindDescPtr^.contentRect.top,
  1278.         WindDescPtr^.contentRect.left, WindDescPtr^.contentRect.bottom,
  1279.         WindDescPtr^.contentRect.right);
  1280.     WriteLn ('WindDescPtr^windowPart=',WindDescPtr^.windowPart);
  1281.     WriteLn ('WindDescPtr^windowRank=',WindDescPtr^.windowRank);
  1282.     WriteLn ('WindDescPtr^windowFlags=',WindDescPtr^.windowFlags);
  1283.     WriteLn ('WindDescPtr^windowVariant=',WindDescPtr^.windowVariant);
  1284.     WriteLn ('WindDescPtr^controlCount=',WindDescPtr^.controlCount);
  1285.     WriteLn ('WindDescPtr^numItems=',WindDescPtr^.numItems);
  1286.     WriteLn ('WindDescPtr^text_name=',WindDescPtr^.text_name);    
  1287. END;
  1288. {$ENDC} 
  1289.  
  1290. {$IFC qDebug}
  1291. PROCEDURE TVUAssist.PrintCtrlReq (CtrlReqPtr :SendCtlInfoParamsPtr);
  1292. BEGIN
  1293.     WriteLn ('CtrlReqPtr^control_rank=', CtrlReqPtr^.control_rank);
  1294.     WriteLn ('CtrlReqPtr^window_rank=', CtrlReqPtr^.window_rank);
  1295. END;
  1296. {$ENDC}
  1297.  
  1298. {$IFC qDebug}
  1299. PROCEDURE TVUAssist.PrintCtrlPoint (CtrlReqPtr :SendFindControlParamPtr);
  1300. BEGIN
  1301.     WriteLn ('CtrlReqPtr=',CtrlReqPtr^.h, CtrlReqPtr^.v);
  1302. END;
  1303. {$ENDC}
  1304.  
  1305. {$IFC qDebug}
  1306. PROCEDURE TVUAssist.PrintCtrlDesc (CtrlDescPtr :MoleCDescPtr);
  1307. BEGIN
  1308.     Write ('CtrlDescPtr^validFlags=');
  1309.     WriteHexInt (CtrlDescPtr^.validFlags);
  1310.     WriteLn;
  1311.     WriteLn ('CtrlDescPtr^owner_rank=',CtrlDescPtr^.owner_rank);
  1312.     WriteLn ('CtrlDescPtr^ctlRect=',CtrlDescPtr^.ctlRect.top,
  1313.         CtrlDescPtr^.ctlRect.left, CtrlDescPtr^.ctlRect.bottom,
  1314.         CtrlDescPtr^.ctlRect.right);
  1315.     WriteLn ('CtrlDescPtr^ctlValue=',CtrlDescPtr^.ctlValue);
  1316.     WriteLn ('CtrlDescPtr^ctlMin=',CtrlDescPtr^.ctlMin);
  1317.     WriteLn ('CtrlDescPtr^ctlMax=',CtrlDescPtr^.ctlMax);
  1318.     WriteLn ('CtrlDescPtr^ctlHilite=',CtrlDescPtr^.ctlHilite);
  1319.     WriteLn ('CtrlDescPtr^part=',CtrlDescPtr^.part);
  1320.     WriteLn ('CtrlDescPtr^ctlRank=',CtrlDescPtr^.ctlRank);
  1321.     WriteLn ('CtrlDescPtr^ctlDefID=',CtrlDescPtr^.ctlDefID);
  1322.     WriteLn ('CtrlDescPtr^text_name=',CtrlDescPtr^.text_name);
  1323. END;
  1324. {$ENDC}
  1325.  
  1326. {$IFC qDebug}
  1327. PROCEDURE TVUAssist.PrintDlogReq (DlogReqPtr :SendDItemInfoPtr);
  1328. BEGIN
  1329.     WriteLn ('DlogReqPtr^item_num=', DlogReqPtr^.item_num);
  1330.     WriteLn ('DlogReqPtr^window_rank=', DlogReqPtr^.window_rank);
  1331. END;
  1332. {$ENDC}
  1333.  
  1334. {$IFC qDebug}
  1335. PROCEDURE TVUAssist.PrintDlogDesc (DlogDescPtr :MoleDItemInfoPtr);
  1336. BEGIN
  1337.     WriteLn ('DlogDescPtr^box=',DlogDescPtr^.box.top,
  1338.         DlogDescPtr^.box.left, DlogDescPtr^.box.bottom,
  1339.         DlogDescPtr^.box.right);
  1340.     WriteLn ('DlogDescPtr^ctlRank=',DlogDescPtr^.ctlRank);
  1341.     WriteLn ('DlogDescPtr^itemType=',DlogDescPtr^.itemType);
  1342.     WriteLn ('DlogDescPtr^item_enabled=',DlogDescPtr^.item_enabled);
  1343.     WriteLn ('DlogDescPtr^has_text=',DlogDescPtr^.has_text);
  1344.     WriteLn ('DlogDescPtr^owner_rank=',DlogDescPtr^.owner_rank);
  1345.     WriteLn ('DlogDescPtr^item_num=',DlogDescPtr^.item_num);
  1346.     WriteLn ('DlogDescPtr^text_name=',DlogDescPtr^.text_name);
  1347. END;
  1348. {$ENDC}
  1349.  
  1350. {$IFC qDebug}
  1351. PROCEDURE TVUAssist.PrintMenuInfoReq (MenuReqPtr :SendMenuInfoParamsPtr);
  1352. BEGIN
  1353.     WriteLn ('MenuReqPtr^menu_rank=', MenuReqPtr^.menu_rank);
  1354.     WriteLn ('MenuReqPtr^menu_ID=', MenuReqPtr^.menu_ID);
  1355. END;
  1356. {$ENDC}
  1357.  
  1358. {$IFC qDebug}
  1359. PROCEDURE TVUAssist.PrintMenuInfoDesc (MenuDescPtr :MoleMenuInfoPtr);
  1360. BEGIN
  1361.     WriteLn ('MenuDescPtr^num_items=', MenuDescPtr^.num_items);
  1362.     WriteLn ('MenuDescPtr^rank=', MenuDescPtr^.rank);
  1363.     WriteLn ('MenuDescPtr^left_edge=', MenuDescPtr^.left_edge);
  1364.     WriteLn ('MenuDescPtr^menuID=', MenuDescPtr^.menuID);
  1365.     WriteLn ('MenuDescPtr^menuWidth=', MenuDescPtr^.menuWidth);
  1366.     WriteLn ('MenuDescPtr^menuHeight=', MenuDescPtr^.menuHeight);
  1367.     WriteLn ('MenuDescPtr^enableFlags=', MenuDescPtr^.enableFlags);
  1368.     WriteLn ('MenuDescPtr^text_name=', MenuDescPtr^.text_name);
  1369. END;
  1370. {$ENDC}
  1371.  
  1372. {$IFC qDebug}
  1373. PROCEDURE TVUAssist.PrintMenuItemReq (MenuReqPtr :SendMenuItemsParamsPtr);
  1374. BEGIN
  1375.     WriteLn ('MenuReqPtr^menu_rank=', MenuReqPtr^.menu_rank);
  1376.     WriteLn ('MenuReqPtr^menu_ID=', MenuReqPtr^.menu_ID);
  1377.     WriteLn ('MenuReqPtr^start_item=', MenuReqPtr^.start_item);
  1378.     WriteLn ('MenuReqPtr^stop_item=', MenuReqPtr^.stop_item);
  1379. END;
  1380. {$ENDC}
  1381.  
  1382. {$IFC qDebug}
  1383. PROCEDURE TVUAssist.PrintMenuItemDesc (MenuDescPtr :MoleDataBlockPtr; OutputSize :integer);
  1384.     VAR
  1385.         index:         Size;
  1386. BEGIN
  1387.     WriteLn ('MenuDescPtr^blockLength=', MenuDescPtr^.blockLength);
  1388.     WriteLn ('OutputSize=', OutputSize);
  1389.     IF OutputSize > 0 THEN
  1390.     BEGIN
  1391.         FOR index := 0 TO OutputSize DO
  1392.             Write(CHR(integer(MenuDescPtr^.dataBlock[index])));
  1393.         WriteLn;
  1394.         WriteLn ('MenuDescPtr^dataBlock= ', MenuDescPtr^.dataBlock);
  1395.     END
  1396.     ELSE
  1397.         WriteLn ('MenuDescPtr^dataBlock= **Empty**');
  1398. END;
  1399. {$ENDC}
  1400.  
  1401. {$IFC qDebug}
  1402. {$S MAFields}
  1403. PROCEDURE TVUAssist.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
  1404.     fieldType: INTEGER)); OVERRIDE;
  1405. BEGIN
  1406.     DoToField('TVUAssist', NIL, bClass);
  1407.     DoToField('fMoleRefNum', @fMoleRefNum, bInteger);
  1408.     INHERITED Fields(DoToField);
  1409. END;
  1410. {$ENDC}
  1411.  
  1412.  
  1413. {========================================== TGridItem ================================}
  1414.  
  1415. {$S VUAssistSeg}
  1416.  
  1417. { Instantiate a TGridItem object, and fill in its fields..  This is here 
  1418. so it can be overridden if you only want rows or columns to show 
  1419. up as seperate user interface items, instead of each individual cells. }
  1420. PROCEDURE TGridItem.IGridItem (theGridView: TGridView; Rank: integer);
  1421. BEGIN
  1422.     SELF.fGridView:=theGridView;
  1423.     SELF.fRank:=Rank;
  1424.     SELF.fRow:=(Rank-1) DIV theGridView.fNumOfCols +1;
  1425.     SELF.fColumn:=(Rank-1) MOD theGridView.fNumOfCols +1;
  1426.     {$IFC qDebug}
  1427.         IF gVUDebug THEN
  1428.             SELF.PrintInstanceVars;
  1429.     {$ENDC}
  1430. END;
  1431.  
  1432. { Provide the bounding rect of a griditem }
  1433. PROCEDURE TGridItem.GetExtent (VAR itsExtent: VRect);
  1434. VAR
  1435.     aCell: GridCell;
  1436. BEGIN
  1437.     aCell.v:=fRow;
  1438.     aCell.h:=fColumn;
  1439.     fGridView.CellToVRect (aCell, itsExtent);
  1440. END;
  1441.  
  1442.  
  1443. { call the LocalToWindow method of the GridView associated with the griditem }
  1444. PROCEDURE TGridItem.LocalToWindow(VAR thePoint: VPoint);
  1445. BEGIN
  1446.     fGridView.LocalToWindow(thePoint);
  1447. END;
  1448.  
  1449.  
  1450. {------------------------------------------------------------------------------------}
  1451. { debugging routines for TGridItem}
  1452.  
  1453. {$IFC qDebug}
  1454. PROCEDURE TGridItem.PrintInstanceVars;
  1455. BEGIN
  1456.     WrLblHexLongint ('TGridItem fGridView=', longint(fGridView));
  1457.     WriteLn;
  1458.     WriteLn ('TGridItem fColumn=', fColumn);
  1459.     WriteLn ('TGridItem fRow=', fRow);
  1460.     WriteLn ('TGridItem fRank=', fRank);
  1461.     WriteLn ('TGridView fNumOfRows=', fGridView.fNumOfRows);
  1462.     WriteLn ('TGridView fNumOfCols=', fGridView.fNumOfCols);
  1463. END;
  1464. {$ENDC}
  1465.  
  1466.  
  1467. {$IFC qDebug}
  1468. {$S MAFields}
  1469. PROCEDURE TGridItem.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
  1470.     fieldType: INTEGER)); OVERRIDE;
  1471. BEGIN
  1472.     DoToField('TGridItem', NIL, bClass);
  1473.     DoToField('fGridView', @fGridView, bObject);
  1474.     DoToField('fColumn', @fColumn, bLongint);
  1475.     DoToField('fRow', @fRow, bLongint);
  1476.     DoToField('fRank', @fRank, bLongint);
  1477.     INHERITED Fields(DoToField);
  1478. END;
  1479. {$ENDC}
  1480.  
  1481.  
  1482.